/**
 * Version 14 mrt 2008 - initial version
 */
package audioreaper.machine;

import audioreaper.tools.AudioUtils;

/**
 * <code>AbstractMachine</code>.
 *
 * @author <a href="mailto:vincent@nazarene.nl">Vincent van Beveren</a>
 *
 */
public abstract class AbstractMachine implements Machine {

	private String _name;
	private MachineContext _context;
	private int _volume;
	private int _panning;
	private boolean _active;
	protected int[] _buffer;
	
	public AbstractMachine(MachineContext context) {
		if (context == null) {
			throw new NullPointerException("'context' may not be null");
		}
		_context = context;
		String name = getClass().getSimpleName();
		if (_context.getNode(name) != null) {
			int i = 1;
			while (_context.getNode(name + i) != null) {
				i++;
			}
			name = name + i;
		}
		_name = name;
		_buffer = context.createBuffer();
		_active = true;
		_panning = MachineContext.PANNING_CENTER;
		_volume = MachineContext.VOLUME_MAX;
	}
	
	
	@Override
	public String getName() {
		return _name;
	}

	@Override
	public void setName(String name) {
		if (name == null) {
			throw new NullPointerException("'name' may not be null");
		}
		if (name.trim().length() == 0) {
			throw new IllegalArgumentException("'name' may not be empty");
		}
		_name = name;		
	}
	
	/* (non-Javadoc)
	 * @see vanbeveren.audioreaper.model.Node#getContext()
	 */
	@Override
	public MachineContext getContext() {
		return _context;
	}


	/**
	 * @return the volume
	 */
	public int getVolume() {
		return _volume;
	}


	/**
	 * @param volume the volume to set
	 */
	public void setVolume(int volume) {
		_volume = volume;
	}


	/**
	 * @return the panning
	 */
	public int getPanning() {
		return _panning;
	}


	/**
	 * @param panning the panning to set
	 */
	public void setPanning(int panning) {
		_panning = panning;
	}


	/**
	 * @return the active
	 */
	public boolean isActive() {
		return _active;
	}


	/**
	 * @param active the active to set
	 */
	public void setActive(boolean active) {
		_active = active;
	}
	
	/**
	 * @return the buffer
	 */
	public int[] getBuffer() {
		return _buffer;
	}
	
	/**
	 * Invoked when this node must render its audio content.
	 */
	protected abstract void renderInternal();
	
	/**
	 * Invoked when this node is inactive. For effects this means bypassed, for instruments
	 * this means disabled. 
	 */
	protected abstract void renderInactive();
	
	public final void render() {
		if (!_active) {
			renderInactive();			
		} else {
			renderInternal();
		}
		AudioUtils.applyPanning(_buffer, _panning);
		AudioUtils.applyVolume(_buffer, _volume);
	}
	
}
